#region (c) 2014 THN Solutions LLC. - All rights reserved
/*
THN TELEPORT version 2

Copyright (c) 2014, THN Solutions LLC. ( www.ThnSolutions.com )
Author: Nguyễn, M. Hải                 ( www.Minh-Hai.com     )
All rights reserved.

This library is dual-licensed.
  + For commercial software, please obtain a commercial license from THN Solutions LLC.

  + For free software, this library is licensed under GPL version 3. A summary of GPLv3 is
    listed below. You should also find a copy of GPLv3 as file License_GPLv3.txt included
	with the source-code files.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License version 3 as published by
    the Free Software Foundation  of the License.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#endregion

#region Using directives
using System;
using System.IO;
using System.CodeDom;
using System.Reflection;
using Thn;
using Thn.Application.Configuration;
using Thn.Communication.Teleporting.Connectors;
using Thn.Communication.Exceptions;
#endregion

namespace Thn.Communication.Teleporting.Settings
{
    /// <summary>
    /// A helper class to load Teleport configuration and setup connectors based on XML file
    /// </summary>
    public class TeleportConfigurator
    {
        #region Auto Initialize
        private bool mAutoInitialize = true;
        /// <summary>
        /// Gets/Sets whether this configurator shall immediately call Initialize method of
        /// connector after loading.
        /// </summary>
        public bool AutoInitialize
        {
            get { return mAutoInitialize; }
            set { mAutoInitialize = value; }
        }
        #endregion

        #region Load
        /// <summary>
        /// Load configuration from file Teleport.xml
        /// </summary>
        public ITeleportConnector Load()
        {
            return this.Load("Teleport.xml", string.Empty);
        }

        /// <summary>
        /// Load configuration from an xml file
        /// </summary>
        /// <param name="filename">Name of the configuration file</param>
        public ITeleportConnector Load(string filename)
        {
            return this.Load(filename, string.Empty);
        }

        /// <summary>
        /// Load configuration from an xml file
        /// </summary>
        /// <param name="filename">Name of the configuration file</param>
        /// <param name="sectionName">If provided, use the specified configuration section instead of the very first one found</param>
        public ITeleportConnector Load(string filename, string sectionName)
        {
            ITeleportConnector connector = null;

            if (!File.Exists(filename)) Thn.Exceptions.FileNotFoundException.Publish(filename);
            else
            {
                SimpleConfigurator config = new SimpleConfigurator();
                config.Load(filename);

                //find config section
                ConfigSection section = null;
                sectionName = sectionName.ToUpper();
                for (int i = 0; i < config.Sections.Count; i++)
                {
                    ConfigSection cs = config.Sections[i];
                    if (cs.ID.ToUpper() == "TELEPORT")
                    {
                        if (sectionName == string.Empty) section = cs;
                        else if (cs["Name"].ToUpper() == sectionName) section = cs;
                    }

                    if (section != null) break;
                }

                if (section == null)
                {
                    if (sectionName == string.Empty) ConfigurationException.Publish_NoTeleportSection();
                    else ConfigurationException.Publish_SectionNotFound(sectionName);

                }
                else connector = ProcessSection(section);
            }

            return connector;
        }
        #endregion

        #region Process Section
        ITeleportConnector ProcessSection(ConfigSection section)
        {
            ITeleportConnector connector = null;

            //if (section["NAME"].ToUpper() == "LOOPBACK") connector = new LoopbackConnector();
            //else
            //{
            //    string connectorName = section["Connector"];
            //    string containerFile = section["ContainerFile"];
            //    object tmp = null;

            //    if (connectorName == string.Empty) ConfigurationException.Publish_NoConnectorName();
            //    else
            //    {
            //        if (containerFile != string.Empty)
            //        {
            //            //load the container Dll
            //            TypeResolver.Register(containerFile);
            //        }

            //        //find Type
            //        Type t = TypeFinder.GetType(connectorName);
            //        if (t == null) ConfigurationException.Publish_ConnectorNotFound(connectorName);
            //        else
            //        {
            //            tmp = Activator.CreateInstance(t);

            //            //ensure the class implements interface ITeleportConnector
            //            if (tmp is ITeleportConnector) connector = (ITeleportConnector)tmp;
            //            else ConfigurationException.Publish_InterfaceNotFound(tmp.GetType());
            //        }

            //    }//has connectorName
            //}

            string connectorName = section["Connector"];
            string containerFile = section["ContainerFile"];
            object tmp = null;

            if (connectorName == string.Empty) ConfigurationException.Publish_NoConnectorName();
            else
            {
                if (containerFile != string.Empty)
                {
                    //load the container Dll
                    TypeResolver.RegisterAllTypes(containerFile, "*");
                }
                else
                {
                    Teleport.RegisterConnectorTypes();
                }

                //find Type
                Type t = TypeFinder.GetType(connectorName);
                if (t == null) ConfigurationException.Publish_ConnectorNotFound(connectorName);
                else
                {
                    tmp = Activator.CreateInstance(t);

                    //ensure the class implements interface ITeleportConnector
                    if (tmp is ITeleportConnector) connector = (ITeleportConnector)tmp;
                    else ConfigurationException.Publish_InterfaceNotFound(tmp.GetType());
                }

            }//has connectorName

            //start up connector
            if (connector != null)
            {
                connector.Configuration = section;
                if (mAutoInitialize) connector.Initialize();
            }

            return connector;
        }
        #endregion

        #region Constructors
        /// <summary>
        /// Default constructor
        /// </summary>
        public TeleportConfigurator()
        { }
        #endregion
    }
}
